package ar.edu.itba.it.cg.grupo01.impl.color;

import java.awt.Color;
import java.util.Collection;
import java.util.List;

public final class Colors {

	public static final Color addTo(Color color, Color... colors) {
		int r = color.getRed();
		int g = color.getGreen();
		int b = color.getBlue();

		for (Color colorToAdd : colors) {
			r += colorToAdd.getRed();
			g += colorToAdd.getGreen();
			b += colorToAdd.getBlue();
		}

		r = (r >= 256) ? 255 : r;
		g = (g >= 256) ? 255 : g;
		b = (b >= 256) ? 255 : b;

		return new Color(r, g, b);
	}

	public static final Color mulTo(Color color, Color... colors) {
		float r = color.getRed() / 255f;
		float g = color.getGreen() / 255f;
		float b = color.getBlue() / 255f;
		for (Color colorToAdd : colors) {
			r *= colorToAdd.getRed() / 255f;
			g *= colorToAdd.getGreen() / 255f;
			b *= colorToAdd.getBlue() / 255f;
		}

		return new Color(r, g, b);
	}

	public static final Color divTo(Color color, Color... colors) {
		float r = color.getRed() / 255f;
		float g = color.getGreen() / 255f;
		float b = color.getBlue() / 255f;

		for (Color colorToAdd : colors) {
			r /= colorToAdd.getRed() / 255f;
			g /= colorToAdd.getGreen() / 255f;
			b /= colorToAdd.getBlue() / 255f;
		}

		return new Color(r, g, b);
	}

	public static Color divTo(Color color, float factor) {
		return Colors.scale(color, 1 / factor);
	}

	public static final Color scale(Color color, float scaleFactor) {

		float scale = (float) scaleFactor;

		float r = color.getRed() / 255f;
		float g = color.getGreen() / 255f;
		float b = color.getBlue() / 255f;

		float finalR = r * scale;
		float finalG = g * scale;
		float finalB = b * scale;

		finalR = (finalR > 1.0f) ? 1.0f : finalR;
		finalG = (finalG > 1.0f) ? 1.0f : finalG;
		finalB = (finalB > 1.0f) ? 1.0f : finalB;

		return new Color(finalR, finalG, finalB);
	}

	public static float getLuminance(Color color) {
		return (0.2989f * color.getRed()) + (0.5866f * color.getGreen())
				+ (0.1145f * color.getBlue());
	}

	public static Color scaleAdd(Color color, float factor, Color addColor) {

		float r = color.getRed() / 255f;
		float g = color.getGreen() / 255f;
		float b = color.getBlue() / 255f;

		float addR = addColor.getRed() / 255f;
		float addG = addColor.getGreen() / 255f;
		float addB = addColor.getBlue() / 255f;

		float finalR = r + (addR * factor);
		float finalG = g + (addG * factor);
		float finalB = b + (addB * factor);

		finalR = (finalR > 1.0f) ? 1.0f : finalR;
		finalG = (finalG > 1.0f) ? 1.0f : finalG;
		finalB = (finalB > 1.0f) ? 1.0f : finalB;

		return new Color(finalR, finalG, finalB);
	}

	public static Color avg(List<Color> allLights) {

		Color result = Color.BLACK;

		for (Color color : allLights) {
			result = Colors.addTo(result, color);
		}

		return Colors.divTo(result, allLights.size());
	}

	public static Color addTo(Color color, Collection<Color> all) {

		Color[] colors = new Color[all.size()];

		int i = 0;
		for (Color single : all) {
			colors[i++] = single;
		}

		return addTo(color, colors);
	}

	public static float clamp(float color) {
		return (color > 1.0f) ? 1.0f : ((color < 0.0f) ? clamp(Math.abs(color))
				: color);
	}

	public static Color getPerlin(float noise, Color noNoise, Color fullNoise) {

		float[] noNoiseColor = noNoise.getRGBColorComponents(null);
		float[] fullNoiseColor = fullNoise.getRGBColorComponents(null);

		float[] perlin = { 0.0f, 0.0f, 0.0f };

		for (int i = 0; i < 3; i++) {
			perlin[i] = noise * noNoiseColor[i] + (1.0f - noise)
					* fullNoiseColor[i];
		}
		return new Color(clamp(perlin[0]), clamp(perlin[1]), clamp(perlin[2]));
	}

}
